/**
 * @file uva/1395/main.cpp
 * @name Slim Span
 * @author Ruiming Guo (guoruiming@stu.scu.edu.cn)
 * @brief
 * 给定一张图，求一棵生成树，使其最大边权与最小边权差最小，输出它们的差值
 * 如果图存在生成树，输出生成树的差值最小的；否则，输出-1。
 *
 * 对于每一个边，“拆掉”（不考虑）比它权值小的边，Kruskal一遍并更新答案
 * TODO: 为啥这样做？我也不知道。
 *
 * @see <https://www.luogu.com.cn/problem/UVA1395>
 * @version 1.0
 * @date 2022-05-01
 *
 * @copyright Copyright (c) 2022
 *
 */
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
struct edge {
  int u, v, w;
  bool operator<(const edge &b) const { return w < b.w; }
} e[N];
typedef long long ll;
int n, m;
int par[N];

int find(int x) { return x == par[x] ? x : par[x] = find(par[x]); }

int maxedge;
bool kruskal(int start_from) {
  for (int i = 1; i <= n; ++i) par[i] = i;
  int cnt = 0;
  maxedge = -1;
  for (int i = start_from; i <= m; ++i) {
    auto [u, v, w] = e[i];
    u = find(u), v = find(v);
    if (u == v) continue;
    par[u] = v;
    if (++cnt == n - 1) {
      // 保存最大边权
      maxedge = w;
      return true;
    }
  }
  return false;
}

int main() {
  while (scanf("%d%d", &n, &m) != EOF && n) {
    for (int i = 1; i <= m; ++i) scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
    int ans = 0x3f3f3f3f;
    sort(e + 1, e + m + 1);
    for (int i = 1; i <= m; ++i) {
      // 从第 i 条边开始计算生成树
      if (kruskal(i)) {
        ans = min(ans, maxedge - e[i].w);
      }
    }
    cout << (ans == 0x3f3f3f3f ? -1 : ans) << endl;
  }
}
